<?php
/**
 * FastApp.
 * 8/21/24
 * @Author 深色的海 (wx:deepsea_0024)
 * @Contact telegram:deepsea159 
 */

namespace App\Marketing\Api\Service;

use App\Fastapp\Api\Service\Account\WalletService;
use App\Fastapp\Api\Service\BaseService;
use App\Fastapp\Exception\TipException;
use App\Fastapp\Model\AccountWallet;
use App\Fastapp\Model\AccountWalletLog;
use App\Marketing\Model\MarketingLotto;
use App\Marketing\Model\MarketingLottoLog;
use App\Marketing\Model\MarketingLottoOpen;
use Hyperf\Database\Model\Builder;

class LottoService extends BaseService
{
    public function detail(string $code): array
    {
        $md = MarketingLotto::query()
            ->select(['id', 'name', 'content', 'open_at', 'pool', 'groups', 'price', 'periods', 'open_type', 'people_num'])
            ->where(['code' => $code])->firstOrFail();
        $md->name = fastapp_lang_text($md->name);
        $md->content = fastapp_lang_text($md->content);
        $paginate = MarketingLottoLog::query()
            ->with(['user:username,mobile,code,email'])
            ->where(['lotto_id' => $md->id, 'periods' => $md->periods])
            ->where('level', '>', 0)
            ->orderBy('level')->simplePaginate();
        $md->open_status = 0;
        $md->logs = array_map(function ($item) {
            $item->username = maskMiddleChars($item->username, 4);
            $item->mobile = maskMiddleChars($item->mobile, 4);
            $item->email = maskMiddleChars($item->email, 4);
            return $item;
        }, $paginate->items());
        $no = [];
        for ($i = 0; $i < 10; $i++) {
            $no[] = drawDoubleColorBall($md->groups);
        }
        $md->no = $no;
        return $md->toArray();
    }

    public function bet(array $param): array
    {
        $param['num'] = $param['num'] ?? 1;
        $md = MarketingLotto::query()->where(['code' => $param['code']])->first();
        $amount = bccomp($md->price, '' . $param['num']);
        $log = null;
        WalletService::dec(['amount' => $amount], function ($data, Builder $query) use ($md, $param, $amount, &$log) {
            $field = 'balance';
            /**@var $wallet AccountWallet */
            $wallet = $query->where($field, '>=', $data['amount'])->first();
            if (!$wallet) throw new TipException(fastapp_t('pay.insufficient_funds'));
            $result['before'] = $wallet->$field;
            $wallet->$field = bcsub($wallet->$field, (string)$data['amount'], $wallet->currency->trade_precision);
            $wallet->save();
            $log = MarketingLottoLog::query()->firstOrCreate([
                'user_id' => get_uid(),
                'lotto_id' => $md->id,
                'no' => $param['no'],
                'periods' => $md->periods,
            ]);
            $log->increment('num', $param['num']);
            $log2 = AccountWalletLog::query()->create([
                'user_id' => $wallet->user_id,
                'wallet_id' => $wallet->id,
                'currency_id' => $wallet->currency_id,
                'type' => AccountWalletLog::USE_BALANCE,
                'object_type' => AccountWalletLog::OBJ_TYPE_LOTTO_LOG,
                'object_id' => $log->id,
                'field' => 'balance',
                'amount' => $amount,
                'before' => $result['before'],
                'after' => $wallet->balance,
            ]);
            $wallet->log_id = $log2->id;
            return $wallet;
        });
        return $log->toArray();
    }

    public function list(array $param): array
    {
        $id = MarketingLotto::query()->where(['code' => $param['code']])->value('id');
        $list = MarketingLottoLog::query()
            ->where(['user_id' => get_uid(), 'id' => $id, 'periods' => $param['periods']])
            ->orderByDesc('id')->get();
        return ['list' => $list];
    }

    public function history(string $code): array
    {
        $id = MarketingLotto::query()->select(['id', 'periods'])->where(['code' => $code])->value('id');
        $paginate = MarketingLottoOpen::query()->where(['lotto_id' => $id])->orderByDesc('periods')->simplePaginate();
        $periods = array_column($paginate->items(), 'periods');
        $logs = MarketingLottoLog::query()
            ->where(['lotto_id' => $id])
            ->whereIn('periods', $periods)
            ->where('level', '>', 0)
            ->orderBy('level')
            ->get()->mapToGroups(function ($item) {
                return [$item->periods => $item];
            });
        $list = [];
        foreach ($paginate->items() as $item) {
            $item->logs = $logs[$item->periods] ?? [];
            $list[] = $item;
        }
        return ['list' => $list];
    }
}